<?php
/**
* Meta box generator for WordPress
*
* @author: Kelvin Zevallos
* @version: 1.0
*
*  Now supports other types of elements that bring their own SHOW/SAVE methods for metaboxes.
*  Altough, these new field-types should bring at least these methods mentioned.
*
*  Thanks to Nikolay Yordanov <me@nyordanov.com> for the code to build up metaboxes so easily.
*/

require_once WP_PLUGIN_DIR . '/diapucp-events/defines.php' ;
require_once DPEM_SMB_PATH . '/smb_validation.php';
//require_once DPEM_SMB_PATH . '/smb_error_handler.php';

class SmartMetaBox {

    protected $meta_box;
    protected $id;
    protected $fields_object; //Array of object-contents that have their own methods.
    protected $validation;    //Object that contains the validation.

/**
 *
 * Declare all the custom fields for events.
 *
 * Method that creates all the custom fields the vents will use, calling the API
 * to create a custom field according to certain specifications. Form more information,
 * check the smarmetabox.php file.
 *
 * @param string $id     The identificator the the metabox. Must be unique.
 * @param array  $opts   Array of options of the metabox:
 *           string title       The title of the metabox.
 *           string pages       The pages where the metabox will appear.
 *           string context     The place where the metabox will be in every edit page.
 *           string priority    The level of priority the metabox will have in it's current context.
 *           bool   validate    Flag that indicates that there must be validation consistency in this metabox.
 *           array  fields      Array that contains the information of each of the metabox's fields. Check each field for more info.
 *
 * @return no returns.
*/
    public function __construct( $id, $opts ) {
        $this->fields_object = array();
        $this->meta_box = $opts;
        $this->id = $id;

        $this->build_objects_array();

        add_action( 'add_meta_boxes', array( &$this, 'add') );
        add_action( 'save_post', array( &$this, 'save') );
/*
        if ( isset($this->meta_box['validate']) and $this->meta_box['validate'] ) {
            $validation = new smb_validation($this->fields_object);
        }
*/
    }


/**
 *
 * Calls all the objects to use in the metabox.
 *
 * Method that calls all the files and definitions required for the fields
 * requested on the constructor.
 *
 * @param no parameters.
 * @return no returns.
*/
    public function build_objects_array(){
        foreach ( $this->meta_box['fields'] as $field ){
            $filepath = DPEM_SMB_FIELDS_PATH . '/' . $field['type'] . '.php';
            $new_field_object = null;
            if ( file_exists( $filepath ) ){
                require_once $filepath;
                call_user_func_array(array( 'smartmeta_' . $field['type'] ,'build_me'),
                                     array($field, &$new_field_object) );
                if ( !empty( $new_field_object ) ){
                    $this->fields_object[] = $new_field_object;
                }
            }
        } //end foreach
    } //end function

/**
 *
 * Adds the metabox definition to the edit page.
 *
 * Method that passes to every page
 *
 * @param no parameters.
 * @return no returns.
*/
    public function add() {
        foreach ( $this->meta_box['pages'] as $page ) {
            add_meta_box($this->id, 
                         $this->meta_box['title'],
                         array(&$this, 'show'),
                         $page,
                         $this->meta_box['context'],
                         $this->meta_box['priority']);
        }
    }

/**
 *
 * Shows all the fields on the metabox.
 *
 * Method that creates the HTML structure and security involved for the metabox
 * and will call all the "show" methods on each type of field instanced.
 *
 * @param object $post The post information.
 * @return no returns.
*/
    public function show($post) {
        if (!empty($this->fields_object)){
            // Use nonce for verification
            ?>
                <input type="hidden" name="<?php echo $this->id ?>_meta_box_nonce"
                       value="<?php echo wp_create_nonce( 'smartmetabox'.$this->id ) ?>" />
                <table class="form-table" id="meta-table-<?php echo $this->id;?>">
                    <tbody>
                        <tr>
                        <?php foreach ($this->fields_object as $one_object) { $one_object->show(); } ?>
                        </tr>
                    </tbody>
                </table>
            <?php
        }
    }

/**
 *
 * Save all the information in the metabox.
 *
 * Method that verifies all the security measues on the show method and calls
 * each save method for each field.
 *
 * @param no parameters.
 * @return no returns.
*/
    public function save($post_id) {
        // verify nonce
        if (!isset($_POST[$this->id.'_meta_box_nonce']) || !wp_verify_nonce($_POST[$this->id.'_meta_box_nonce'], 'smartmetabox'.$this->id)) {
            return $post_id;
        }
        // check autosave
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; }

        // check permissions
        if ('post' == $_POST['post_type']) {
            if (!current_user_can('edit_post', $post_id)) { return $post_id; }
        } elseif (!current_user_can('edit_page', $post_id)) { return $post_id; }

        //Save each object according to it's own save method.
        foreach ($this->fields_object as $one_object) { $one_object->save($post_id); }
    }

} //End Class

/**
 *
 * Save all the information in the metabox.
 *
 * Method that verifies all the security measues on the show method and calls
 * each save method for each field.
 *
 * @param no parameters.
 * @return no returns.
*/
function add_smart_meta_box($id, $opts) {
    return new SmartMetaBox($id, $opts);
}
?>


